﻿Shader "Kun URP/Post Process/ScanLine"
{
    Properties
    {
        [HideInInspector]_MainTex("MainTex",2D) = "white"{}
        [HDR]_ColorX("ColorX", Color) = (1, 1, 1, 1)
        [HDR]_ColorY("ColorY", Color) = (1, 1, 1, 1)
        [HDR]_ColorZ("ColorZ", Color) = (1, 1, 1, 1)
        [HDR]_ColorEdge("ColorEdge", Color) = (1, 1, 1, 1)
        _Width("Width", float) = 0.02

        [HDR]_ColorOutline("ColorEdge", Color) = (1, 1, 1, 1)
        _NormalSensitivity("Normal Sensitivity", float) = 1
        _DepthSensitivity("Depth Sensitivity", float) = 1
        _Speed("Speed", float) = 1
        _EdgeSample("Edge Sample", Range(0, 1)) = 1
        _Ratio("Ratio", Range(-20, 20)) = 0
    }
    SubShader
    {
        Tags{
            "RenderPipeline"="UniversalRenderPipeline"
        }
        Cull Off ZWrite Off ZTest Always
        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        CBUFFER_START(UnityPerMaterial)
            float4 _MainTex_TexelSize;
        CBUFFER_END
        float4 _ColorX;
        float4 _ColorY;
        float4 _ColorZ;
        float4 _ColorEdge;
        float4 _ColorOutline;
        float _Width;
        float _EdgeSample;
        float _Speed;
        float _NormalSensitivity;
        float _DepthSensitivity;
        float _Ratio;
        float4x4 _Matrix;
        TEXTURE2D( _MainTex);
        SAMPLER(sampler_MainTex);
        TEXTURE2D( _CameraDepthTexture);
        SAMPLER(sampler_CameraDepthTexture);
        TEXTURE2D( _CameraDepthNormalsTexture);
        SAMPLER(sampler_CameraDepthNormalsTexture);
        struct a2v
        {
            float4 positionOS   :POSITION;
            float2 texcoord     :TEXCOORD;
        };
        struct v2f
        {
            float4 positionCS   :SV_POSITION;
            float2 texcoord     :TEXCOORD;
            float3 direction    :TEXCOORD1;
        };
        ENDHLSL
        pass
        {
            HLSLPROGRAM
            #pragma vertex VERT
            #pragma fragment FRAG
            #pragma multi_compile_local _AXIS_X _AXIS_Y _AXIS_Z
            int sobel(v2f i)
            {
                real depth[4];
                real2 normal[4];
                float2 uv[4];
                uv[0] = i.texcoord + float2(-1, -1) * _EdgeSample * _MainTex_TexelSize.xy;
                uv[1] = i.texcoord + float2(1, -1) * _EdgeSample * _MainTex_TexelSize.xy;
                uv[2] = i.texcoord + float2(-1, 1) * _EdgeSample * _MainTex_TexelSize.xy;
                uv[3] = i.texcoord + float2(1, 1) * _EdgeSample * _MainTex_TexelSize.xy;
                for (int t = 0; t < 4; t++)
                {
                    real4 depthNormalTex = SAMPLE_TEXTURE2D(_CameraDepthNormalsTexture, sampler_CameraDepthNormalsTexture, uv[t]);
                    normal[t] = depthNormalTex.xy;
                    depth[t] = depthNormalTex.z * 1.0 + depthNormalTex.w / 255.0;
                }
                int Dep = abs(depth[0] - depth[3]) * abs(depth[1] - depth[2]) * _DepthSensitivity > 0.01 ? 1 : 0;
                float2 nor = abs(normal[0] - normal[3]) * abs(normal[1] - normal[2]) * _NormalSensitivity;
                int Nor = (nor.x + nor.y) > 0.01 ? 1 : 0;
                return saturate(Dep + Nor);
            }
            v2f VERT(a2v i)
            {
                v2f o;
                o.positionCS = TransformObjectToHClip(i.positionOS.xyz);
                o.texcoord = i.texcoord;
                int t = 0;
                if (i.texcoord.x < 0.5 && i.texcoord.y < 0.5)
                    t = 0;
                else if (i.texcoord.x > 0.5 && i.texcoord.y < 0.5)
                    t = 1;
                else if (i.texcoord.x > 0.5 && i.texcoord.y > 0.5)
                    t = 2;
                else
                    t = 3;
                o.direction = _Matrix[t].xyz;
                return o;
            }
            half4 FRAG(v2f i):SV_TARGET
            {
                int outline = sobel(i);
                // return _ColorEdge;
                float4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);
                // return lerp(tex, _ColorOutline, outline);
                float4 depthNormal = SAMPLE_TEXTURE2D(_CameraDepthNormalsTexture, sampler_CameraDepthNormalsTexture, i.texcoord);
                float depth01 = depthNormal.z * 1.0 + depthNormal.w * 1 / 255.0;
                float newDepth01 = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, i.texcoord);
                newDepth01 = Linear01Depth(newDepth01, _ZBufferParams).x;
                // return newDepth01;
                float3 positionWS = _WorldSpaceCameraPos + newDepth01 * i.direction * _ProjectionParams.z + float3(0.1, 0.1, 0.1);
                float3 positionWS01 = positionWS * _ProjectionParams.w;
                float3 linePos = step(1 - _Width, frac(positionWS));
                float4 lineColor = linePos.x * _ColorX + linePos.y * _ColorY + linePos.z * _ColorZ + outline * _ColorOutline;
                // return positionWS01;
                #ifdef _AXIS_X
                    // float mask = saturate(pow(abs(frac(positionWS01.x + _Ratio * 0.1 * _Speed) - 0.75), 10) * 30);
                    float delta = (positionWS.x - _Ratio) * 0.2;
                    float mask = saturate(step(delta, 1) * delta);
                    // mask += step(0.999, mask);
                #elif _AXIS_Y
                    float mask = saturate(pow(abs(frac(positionWS01.y + _Ratio * 0.1 * _Speed) - 0.75), 10) * 30);
                    mask += step(0.999, mask);
                #elif _AXIS_Z
                    float mask = saturate(pow(abs(frac(positionWS01.z + _Ratio * 0.1 * _Speed) - 0.75), 10) * 30);
                    mask += step(0.999, mask);
                #endif
                // return step(1, 1);
                return tex * saturate(1 - mask) + (lineColor + _ColorEdge) * mask;
            }
            
            ENDHLSL
        }
    }
}
